﻿using System.Data;
using System.Runtime.InteropServices;
using TPXSDK.NET.Share;

namespace TPXSDK.NET.Log;

/// <summary>
/// POS日志数据结构
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct LogEntryPos
{
    public ushort SN;   // sequential encoding number        
    public short Roll;  // range: -90~+90, Units: centi-deg  
    public short Pitch; // range: -90~+90, Units: centi-deg  
    public ushort Yaw;  // range: 0~35999, Units: centi-deg  
    public int Lat;     // lat of camera snap pos in deg*1e7 
    public int Lng;     // lng of camera snap pos in deg*1e7 
    public int Alt;     // alt of camera snap pos in cm      
    public uint TS;     // timestamp for camera snap in ms   

    public readonly string[] StrVal => [$"{SN}", $"{Roll * 0.01f:F2}", $"{Pitch * 0.01f:F2}", $"{Yaw * 0.01f:F2}", $"{Lat / 10e6:F7}", $"{Lng / 10e6}", $"{Alt * 0.01f:F2}", $"{TS}"];
    public static string[] StrMem => ["SN", "Roll", "Pitch", "Yaw", "Lat", "Lng", "Alt", "TS"];

    public static DataTable Load(Stream fs, LogParserBase? parser = null)
    {
        var dataTab = DataUtils.Reflect2DataTable<LogEntryPos>("PosLogEntry");
        using var sr = new StreamReader(fs);
        //remove header
        sr.ReadLine();
        while (!sr.EndOfStream)
        {
            var line = sr.ReadLine();
            if (string.IsNullOrEmpty(line)) continue;
            var segs = line.Split(['\t'], StringSplitOptions.RemoveEmptyEntries);
            if (dataTab.Columns.Count != segs.Length) continue;
            var dr = dataTab.NewRow();
            FillRowData(segs, dr);
            dataTab.Rows.Add(dr);
            parser?.Report(dataTab.Rows.Count);
        }

        return dataTab;
    }

    private static void FillRowData(string[] segs, DataRow dr)
    {
        dr[0] = Convert.ToUInt16(segs[0]);//SN
        dr[1] = Convert.ToSingle(segs[1]);//Roll
        dr[2] = Convert.ToSingle(segs[2]);//Pitch
        dr[3] = Convert.ToSingle(segs[3]);//Yaw

        dr[4] = Convert.ToDouble(segs[4]);//Lat
        dr[5] = Convert.ToDouble(segs[5]);//Lng
        dr[6] = Convert.ToSingle(segs[6]);//Alt
        dr[7] = Convert.ToUInt32(segs[7]);//TS
    }
}
